<template>
  <div class="mb-4 flex justify-between">
    <n-space>
      <n-input v-model:value="tokenState.searchValue" placeholder="搜索token" @update:value="changeSearchVal" clearable />
      <n-button :disabled="!tokenState.checkedRowKeys.length" type="error"
        @click="delToken(tokenState.checkedRowKeys)">删除选中
      </n-button>
    </n-space>
    <div>
      <n-button type="primary" @click="openTokenModal('add')">创建token
      </n-button>
    </div>
  </div>

  <n-data-table :bordered="false" :checked-row-keys="tokenState.checkedRowKeys" :columns="tokenState.columns"
    :data="tokenState.data" :pagination="pagination" :row-key="row => row.id" remote size="large" flex-height
    @update:checked-row-keys="rows => tokenState.checkedRowKeys = rows" :scroll-x="900" :loading="mainStore.pageLoading">
    <template #empty>
      <n-empty description="暂无token"></n-empty>
    </template>
  </n-data-table>

  <BasicModal :title="tokenState.modalInfo.positiveText + 'token'" to="#app" @confirm="addEditToken"
    @register="tokenModalRegister">
    <n-form ref="tokenFormRef" :model="tokenState.formData" :rules="tokenState.rules"
      require-mark-placement="right-hanging">
      <div v-if="tokenState.modalInfo.positiveText === '创建'">
        <n-form-item label="token" path="tokens">
          <n-input type="textarea" :autosize="{ minRows: 6, maxRows: 100 }" class="max-h-[200px]"
                  :allow-input="noSideSpace" v-model:value="tokenState.formData.tokens"
                  placeholder="请输入要创建的token（一行一个）" />
        </n-form-item>
      </div>
      <div v-else>
        <n-form-item label="token" path="accessKey">
          <n-input :allow-input="noSideSpace" v-model:value="tokenState.formData.accessKey" placeholder="请输入token" />
        </n-form-item>
        <n-form-item label="使用状态" path="state" label-placement="left">
          <n-radio-group v-model:value="tokenState.formData.state">
            <n-radio :value="0">未使用</n-radio>
            <n-radio :value="1">使用中</n-radio>
          </n-radio-group>
        </n-form-item>
      </div>
    </n-form>
  </BasicModal>
</template>

<script setup>
import { useNotification, NSpace, NButton, NDescriptions, NDescriptionsItem, NTag, NIcon } from 'naive-ui'
import { h, reactive, getCurrentInstance, defineAsyncComponent } from 'vue'
import { tokenList, deleteToken, updateToken, createToken } from '@api/tokenApi'
import { useMainStore } from '@/store'
import { timeFormat, copyText, noSideSpace } from '@/utils'
import { useDialog } from '@/hook/popup/useDialog'
import { useModal } from '@c/Modal/useModal'
import { TrashOutline, CopyOutline } from '@vicons/ionicons5'

const BasicModal = defineAsyncComponent(() => import('@c/Modal/BasicModal.vue'))
const { proxy } = getCurrentInstance()
const notification = useNotification()
const mainStore = useMainStore()

const tokenForm = {
  tokens: '',
}

const tokenState = reactive({
  creating: false,
  data: [],
  modalInfo: {
    positiveText: '',
  },
  searchValue: '',
  formData: {},
  checkedRowKeys: [],
  rules: {
    tokens: { required: true, message: 'token不能为空', trigger: 'input' },
    accessKey: { required: true, message: 'token不能为空', trigger: 'input' },
  },
  columns: [
    { type: 'selection' },
    {
      type: 'expand',
      renderExpand: row => {
        return h(NDescriptions, { columns: 1, labelPlacement: 'left' }, {
          default: () => [
            h(NDescriptionsItem, { label: '创建时间' }, {
              default: () => h(NTag, { type: 'primary', size: 'small' }, { default: () => timeFormat(row.createdAt) }),
            }),
            h(NDescriptionsItem, { label: '修改时间' }, {
              default: () => h(NTag, { type: 'primary', size: 'small' }, { default: () => timeFormat(row.updatedAt) }),
            }),
          ],
        })
      },
    },
    { title: 'id', key: 'id', minWidth: 90, width: 90 },
    { title: 'token', key: 'accessKey', minWidth: 160, ellipsis: { tooltip: true } },
    {
      minWidth: 50, width: 50, render(row) {
        return h(NButton, { type: 'primary', text: true, size:'large', title: '复制token' }, {
          default: () => h(NIcon, {
            component: CopyOutline,
            onClick() {
              copyText(row.accessKey)
            }
          }, null)
        })
      }
    },
    { title: 'usedToken', key: 'usedToken', minWidth: 100, width: 100 },
    {
      title: '使用状态', key: 'state', minWidth: 90, render(row) {
        let text, type
        switch (row.state) {
          case 0:
            text = '未使用'
            type = 'default'
            break
          case 1:
            text = '使用中'
            type = 'primary'
            break
        }
        return h(NTag, { type }, {
          default: () => text
        })
      }
    },
    {
      title: '操作', minWidth: 120, width: 120,
      render(row) {
        return h(NSpace, {}, {
          default: () => [
            h(NButton, {
              type: 'primary',
              class: 'mt-1',
              size: 'small',
              onclick() {
                openTokenModal('edit', row)
              },
            }, { default: () => '编辑' }),
            h(NButton, {
              type: 'error',
              size: 'small',
              title: '删除token',
              class: 'mt-1',
              onclick() {
                delToken([row.id])
              },
            }, { default: () => h(NIcon, { component: TrashOutline, size: 16 }, {}) }),
          ],
        })
      },
    }
  ],
})

const pagination = reactive({
  ...mainStore.pagination,
  onChange(page) {
    pagination.page = page
    getTokenList()
  },
  onUpdatePageSize(pageSize) {
    pagination.page = 1
    pagination.pageSize = pageSize
    getTokenList()
  },
})

const [
  tokenModalRegister, {
    openModal: basicOpenTokenModal,
    closeModal: closeTokenModal,
    setModalLoading: setTokenModalLoading,
  }] = useModal(tokenState.modalInfo)

const openTokenModal = (type, item = {}) => {
  tokenState.modalInfo.positiveText = type === 'add' ? '创建' : '修改'
  tokenState.formData = type === 'add' ? { ...tokenForm } : { ...item }
  basicOpenTokenModal()
}

const getTokenList = async () => {
  try {
    mainStore.setPageLoading(true)
    const res = await tokenList({ page: pagination.page, limit: pagination.pageSize, search: tokenState.searchValue })
    if (res?.statusCode === 200) {
      tokenState.data = res.data.rows
      pagination.itemCount = res.data.count
    }
  } finally {
    mainStore.setPageLoading(false)
  }
}
getTokenList()

const addEditToken = () => {
  proxy.$refs.tokenFormRef.validate(async validate => {
    if (validate) return false
    try {
      setTokenModalLoading(true)
      let api = null
      let formData = { ...tokenState.formData }
      if (tokenState.modalInfo.positiveText === '创建') {
        api = createToken
        formData.tokens = []
        const tokenArr = tokenState.formData.tokens.split('\n')
        tokenArr.forEach((item)=>{
          item.trim() ? formData.tokens.push(item.trim()) : ''
        })
      } else {
        api = updateToken
      }
      const res = await api(formData)
      if (res?.statusCode !== 200) return false
      closeTokenModal()
      await getTokenList()
      $message.success(res.message,{ duration: 1000 })
    } finally {
      setTokenModalLoading(false)
    }
  })
}

const delToken = ids => {
  const delDialog = useDialog({
    title: '删除',
    content: `是否删除${tokenState.checkedRowKeys.length > 1 ? '这些' : '该'}token?`,
    type: 'error',
    icon: true,
    async confirm() {
      const res = await deleteToken({ id: [...ids] })
      if (res?.statusCode === 200) {
        delDialog.destroy()
        tokenState.checkedRowKeys = []
        await getTokenList()
        $message.success(res.message)
      }
    },
  })
}

let timer = null
const changeSearchVal = val => {
  clearTimeout(timer)
  timer = setTimeout(() => {
    getTokenList()
  }, 300)
}
</script>

<style lang="less" scoped></style>
